home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK v1.3f3 / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  1999-08-20  |  15.6 KB  |  447 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19.  
  20. usbCompositePBStruct newInterfacesPB;
  21.  
  22. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  23. {
  24.     paramblock->usbReference = theDeviceRef;
  25.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  26.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  27.     paramblock->pbVersion = kUSBCurrentPBVersion;
  28.     paramblock->usb.cntl.WIndex = 0;             
  29.     paramblock->usbBuffer = nil;        
  30.     paramblock->usbStatus = kUSBNoErr;
  31.     paramblock->usbReqCount = 0;
  32.     paramblock->usbActCount = 0;
  33.     paramblock->usb.cntl.WValue = 0;
  34.     paramblock->usbFlags = 0;
  35. }
  36.  
  37.  
  38. Boolean immediateError(OSStatus err)
  39. {
  40.     return((err != kUSBPending) && (err != kUSBNoErr) );
  41. }
  42.  
  43. void CompositeDeviceInitiateTransaction(USBPB *pb)
  44. {
  45. register usbCompositePBStruct *pCompositePB;
  46. OSStatus myErr;
  47.  
  48.     pCompositePB = (usbCompositePBStruct *)(pb);
  49.  
  50.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  51.         return;
  52.         
  53.     pCompositePB->transDepth++;
  54.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  55.     {
  56.     
  57.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  58.     }
  59.     
  60.     if (pCompositePB->driverRemovalPending)
  61.     {
  62.         pCompositePB->pb.usbRefcon = kReturnFromDriver;
  63.         return;
  64.     }
  65.  
  66.     switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  67.     {
  68.         case kResetDevice:
  69.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  70.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  71.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  72.             myErr = USBResetDevice(pb);
  73.             if(immediateError(myErr))
  74.             {
  75.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kResetDevice - immediate error", myErr);
  76.             }
  77.             break;
  78.  
  79.         case kGetFullConfiguration0:
  80.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  81.             pCompositePB->pb.usb.cntl.WIndex = 0;             
  82.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  83.             
  84.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  85.             myErr = USBGetFullConfigurationDescriptor(pb);
  86.             if(immediateError(myErr))
  87.             {
  88.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration (#1) - immediate error", myErr);
  89.             }
  90.             break;
  91.         
  92.         case kSetConfig:
  93.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  94.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
  95.             
  96.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig;
  97.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue;         /* Use configuration ID value from descriptor */
  98.             
  99.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  100.             
  101.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  102.             myErr = USBDeviceRequest(pb);
  103.             if(immediateError(myErr))
  104.             {
  105.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetConfig - immediate error", myErr);
  106.             }
  107.             break;
  108.             
  109.         case kSetRemoteWakeup:            
  110.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  111.             
  112.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);            
  113.             
  114.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetFeature;
  115.             pCompositePB->pb.usb.cntl.WValue = kUSBFeatureDeviceRemoteWakeup; 
  116.             pCompositePB->pb.usb.cntl.WIndex = 0;
  117.             
  118.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  119.             
  120.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  121.             myErr = USBDeviceRequest(pb);
  122.             if(immediateError(myErr))
  123.             {
  124.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetRemoteWakeup - immediate error", myErr);
  125.             }
  126.             break;
  127.  
  128.         case kNewInterfaceRef:
  129.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  130.             // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
  131.             // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  132.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex;
  133.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  134.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  135.  
  136.             myErr = USBNewInterfaceRef(pb);
  137.             if(immediateError(myErr))
  138.             {
  139.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr);
  140.             }
  141.             break;
  142.             
  143.         default:
  144.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  145.             pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  146.             break;
  147.     }
  148.     
  149. // At this point the control is returned to the system.  If a USB transaction
  150. // has been initiated, then it will call the Complete procs
  151. // (below) to handle the results of the transaction.
  152. }
  153.  
  154. void CompositeDeviceCompletionProc(USBPB *pb)
  155. {
  156. OSStatus myErr;
  157. register usbCompositePBStruct *pCompositePB;
  158. USBInterfaceDescriptorPtr pInterfaceDescriptor;
  159. UInt32 i;
  160.  
  161.     pCompositePB = (usbCompositePBStruct *)(pb);
  162.  
  163.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  164.         return;
  165.         
  166.     pCompositePB->transDepth--;
  167.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  168.     {
  169.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth);
  170.     }
  171.     
  172.     if ((pCompositePB->pb.usbStatus == kUSBEndpointStallErr) && 
  173.         (pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kSetRemoteWakeup){
  174.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Device does not support RemoteWakeup (Config descriptor is wrong)", pCompositePB->partialConfigDescriptor.attributes);
  175.         pCompositePB->pb.usbStatus = kUSBNoErr;
  176.     }
  177.     
  178.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  179.     {
  180.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus);
  181.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  182.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  183.         pCompositePB->retryCount--;
  184.         if (!pCompositePB->retryCount)
  185.         {
  186.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon);
  187.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  188.             return;
  189.         }
  190.     }
  191.     else
  192.     {
  193.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  194.         pCompositePB->retryCount = kCompositeRetryCount;
  195.     }
  196.  
  197.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  198.     {                                                
  199.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  200.         switch(pCompositePB->pb.usbRefcon)
  201.         {
  202.             case kResetDevice:            /* Device is not reset */
  203.                 pCompositePB->pb.usbRefcon = kGetFullConfiguration0;
  204.                 break;
  205.  
  206.             case kGetFullConfiguration0:
  207.                 pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
  208.                 if (pCompositePB->pFullConfigDescriptor == nil)
  209.                 {
  210.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
  211.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  212.                     break;
  213.                 }
  214.                 
  215.                 BlockCopy(   (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) )  );
  216.                 USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" - Configuration->maxPower = ", pCompositePB->pFullConfigDescriptor->maxPower);
  217.                 USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" -      Hub supplied power = ", pCompositePB->busPowerAvailable);
  218.                 if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
  219.                 {
  220.                     pCompositePB->pb.usbRefcon = kSetConfig;
  221.                 }
  222.                 else
  223.                 {
  224.                     USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
  225.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, kCompositeDriverName" - Insufficient power for device", pCompositePB->busPowerAvailable);
  226.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  227.                 }
  228.                 break;
  229.                 
  230.             case kSetConfig:            /* get all the interface descriptors and save them */
  231.                 for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
  232.                 {
  233.                     pCompositePB->interfaceRefArray[i] = 0;
  234.                     myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
  235.                     if (kUSBNoErr == myErr)
  236.                     {
  237.                         BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
  238.                     }
  239.                     else                /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */
  240.                     {
  241.                         pCompositePB->interfaceDescriptors[i].length = 0;
  242.                     }
  243.                 }
  244.                 pCompositePB->interfaceIndex = 0;
  245.                 pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
  246.                 pCompositePB->pb.usbRefcon = 
  247.                     (pCompositePB->partialConfigDescriptor.attributes & kUSBAtrRemoteWakeup) ? kSetRemoteWakeup : kNewInterfaceRef;
  248.                 break;
  249.  
  250.             case kSetRemoteWakeup:            
  251.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  252.                 break;
  253.                 
  254.             case kNewInterfaceRef:
  255.                 /* save the new interface ref for this interface */
  256.                 pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
  257.                 
  258.                 /* only install the interface driver if we had a valid interface descriptor */
  259.                 if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0)
  260.                 {
  261.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
  262.                 }
  263.                 
  264.                 /* advance to the next interface */
  265.                 pCompositePB->interfaceIndex++;
  266.                 
  267.                 /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */
  268.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  269.                 {
  270.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  271.                 }
  272.                 else
  273.                 {
  274.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  275.                 }
  276.                 break;
  277.             
  278.             default:
  279.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  280.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  281.                 break;
  282.         }
  283.     }
  284.     if (!(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending))
  285.         CompositeDeviceInitiateTransaction(pb);
  286.  
  287. }
  288.  
  289. // entry points, moved from CompositeDriverDescription.c
  290.  
  291. // hubDriverInitInterface function
  292. // Called to initialize driver for an individual interface - either by expert or
  293. // internally by driver
  294. OSStatus CompositeDriverInitInterface(
  295.             UInt32                         interfaceNum, 
  296.             USBInterfaceDescriptor        *interfaceDesc, 
  297.             USBDeviceDescriptor            *deviceDesc, 
  298.             USBDeviceRef                 device)
  299. {
  300. #pragma unused (interfaceNum)
  301. #pragma unused (interfaceDesc)
  302. #pragma unused (deviceDesc)
  303. #pragma unused (device)
  304.  
  305.     return (OSStatus)kUSBNoErr;
  306. }
  307.  
  308. OSStatus    CompositeDriverNotifyProc(UInt32     notification, void *pointer, UInt32 refcon)
  309. {
  310. #pragma unused (pointer)
  311. #pragma unused (refcon)
  312.  
  313. OSStatus    myErr;
  314. OSStatus     status = kUSBNoErr;
  315. UInt32        count = 0;
  316. static    UInt32    interfacenum = 0;
  317.  
  318.     switch (notification)
  319.     {
  320.         case kNotifyExpertTerminating:                                // TCC <USB15>
  321.                 newInterfacesPB.expertTerminatePending = true;
  322.                 while (count < newInterfacesPB.interfaceCount)
  323.                         USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaceRefArray[count++]);
  324.                 return(noErr);
  325.             break;
  326.         case kNotifyDriverBeingRemoved:
  327.             newInterfacesPB.driverRemovalPending = true;
  328.             
  329.             if (newInterfacesPB.pb.usbRefcon & kCompletionPending)
  330.             {
  331.                 USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for transaction to complete", newInterfacesPB.pb.usbRefcon);
  332.                 status = kUSBDeviceBusy;
  333.             }
  334.             else
  335.             {
  336.                 if (interfacenum == 0)
  337.                     newInterfacesPB.pb.usbStatus = kUSBNoErr;
  338.                 
  339.                 if (newInterfacesPB.pb.usbStatus == kUSBPending)
  340.                 {
  341.                     USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for Dispose/Deallocate to complete", newInterfacesPB.pb.usbRefcon);
  342.                     status = kUSBDeviceBusy;
  343.                 }
  344.                 else
  345.                 {
  346.                     if (interfacenum < newInterfacesPB.interfaceCount)        
  347.                     {
  348.                         USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaceRefArray[interfacenum]);
  349.                         InitParamBlock(newInterfacesPB.interfaceRefArray[interfacenum], &newInterfacesPB.pb);
  350.                         newInterfacesPB.pb.usbRefcon = 0;             
  351.                         newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  352.                         myErr = USBDisposeInterfaceRef(&newInterfacesPB.pb);
  353.                         if(immediateError(myErr))
  354.                         {
  355.                             USBExpertFatalError(newInterfacesPB.interfaceRefArray[interfacenum], kUSBInternalErr, kCompositeDriverName" - USBDisposeInterfaceRef - immediate error", myErr);
  356.                         }
  357.                         interfacenum++;
  358.                         status = kUSBDeviceBusy;
  359.                     }
  360.                     else
  361.                     {
  362.                         if (newInterfacesPB.pFullConfigDescriptor)
  363.                         {
  364.                             InitParamBlock(newInterfacesPB.deviceRef, &newInterfacesPB.pb);
  365.                             newInterfacesPB.pb.usbRefcon = 0;             
  366.                             newInterfacesPB.pb.usbBuffer = newInterfacesPB.pFullConfigDescriptor;        
  367.                             newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  368.                             myErr = USBDeallocMem(&newInterfacesPB.pb);
  369.                             newInterfacesPB.pFullConfigDescriptor = nil;
  370.                             status = kUSBDeviceBusy;
  371.                         }
  372.                         else
  373.                         {
  374.                             status = kUSBNoErr;
  375.                         }
  376.                     }
  377.                 }
  378.             }
  379.             break;
  380.             
  381.         default:
  382.             break;
  383.     }
  384.     return status;
  385. }
  386.  
  387. // Hardware Validation
  388. // Called upon load by Expert
  389. OSStatus CompositeDriverValidateHW(USBDeviceRef device, USBDeviceDescriptor *desc)
  390. {
  391. #pragma unused (device)
  392. #pragma unused (desc)
  393.  
  394.     return (OSStatus)kUSBNoErr;
  395. }
  396.  
  397. // Initialization function
  398. // Called upon load by Expert
  399. OSStatus     CompositeDriverInitialize (USBDeviceRef device, USBDeviceDescriptorPtr pDesc,  UInt32 busPowerAvailable)
  400. {
  401.     // don't let a race condition occur; prevent finalizing until we're all done.
  402.     DeviceInitialize(device, pDesc, busPowerAvailable);
  403.     return (OSStatus)kUSBNoErr;
  404. }
  405.  
  406. // Termination function
  407. // Called by Expert when driver is being shut down
  408. OSStatus CompositeDriverFinalize(USBDeviceRef theDeviceRef, USBDeviceDescriptorPtr pDesc)
  409. {
  410. #pragma unused (pDesc)
  411.  
  412.     USBExpertStatus(theDeviceRef, kCompositeDriverName" - Finalize", 0);
  413.     return (OSStatus)kUSBNoErr;
  414. }
  415.  
  416. void DeviceInitialize(USBDeviceRef device, USBDeviceDescriptorPtr pDeviceDescriptor, UInt32 busPowerAvailable)
  417. {
  418. static Boolean beenThereDoneThat = false;
  419.  
  420.     if(beenThereDoneThat)
  421.     {
  422.         USBExpertFatalError(device, kUSBInternalErr, kCompositeDriverName" is not reentrant!", 0);
  423.         return;
  424.     }
  425.     beenThereDoneThat = true;
  426.     
  427.     newInterfacesPB.driverRemovalPending = false;
  428.     newInterfacesPB.expertTerminatePending = false;
  429.     
  430.     newInterfacesPB.deviceRef = device;    
  431.     newInterfacesPB.deviceDescriptor = *pDeviceDescriptor;    
  432.     
  433.     newInterfacesPB.busPowerAvailable = busPowerAvailable;                            
  434.     newInterfacesPB.delayLevel = 0;                            
  435.     newInterfacesPB.transDepth = 0;                            
  436.     newInterfacesPB.retryCount = kCompositeRetryCount;
  437.     newInterfacesPB.pFullConfigDescriptor = nil;
  438.     
  439.     InitParamBlock(device, &newInterfacesPB.pb);
  440.     newInterfacesPB.pb.usbRefcon = kResetDevice;            /* Start out at first state */
  441.     
  442. //    DebugStr("\pIn Composite Driver");
  443.     CompositeDeviceInitiateTransaction(&newInterfacesPB.pb);
  444. }
  445.  
  446.  
  447.